package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.data.service.RichTextService;
import com.xbongbong.paas.domain.entity.AttrTrashEntity;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasFormRichTextEntity;
import com.xbongbong.paas.domain.entity.PaasProcessRichTextEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.thread.LogThreadPoolBeanConfig;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataUpdateDTO;
import com.xbongbong.paas.pojo.dto.FormRichTextBatchDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.pro.enums.RichTextEnum;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.PaasFormRichTextModel;
import com.xbongbong.saas.model.PaasProcessRichTextModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.domain.entity.WorkflowBackupRichTextEntity;
import com.xbongbong.workflow.model.WorkflowBackupRichTextModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * 富文本业务层实现
 *
 * @author LiZhikang
 * @date 2022/7/28 9:29
 */
@Service("richTextService")
@Slf4j
public class RichTextServiceImpl implements RichTextService {

    @Resource
    private PaasFormRichTextModel paasFormRichTextModel;

    @Resource
    private PaasProcessRichTextModel paasProcessRichTextModel;

    @Resource
    private WorkflowBackupRichTextModel workflowBackupRichTextModel;

    @Resource
    private CommonHelp commonHelp;

    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;

    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private LogThreadPoolBeanConfig logThreadPoolBeanConfig;

    @Override
    public void saveFormRichText(FormDataAddDTO formDataAddDTO, PaasFormDataEntity paasFormDataEntity, Object richTextData) {
        if (Objects.isNull(richTextData)) {
            return;
        }
        PaasFormRichTextEntity paasFormRichTextEntity = new PaasFormRichTextEntity();
        BeanUtil.copyProperties(paasFormDataEntity, paasFormRichTextEntity);
        paasFormRichTextEntity.setId(null);
        paasFormRichTextEntity.setSaasMark(formDataAddDTO.getSaasMark());
        paasFormRichTextEntity.setBusinessType(formDataAddDTO.getBusinessType());
        paasFormRichTextEntity.setDistributorMark(Optional.ofNullable(formDataAddDTO.getDistributorMark()).orElse(BasicConstant.ZERO));
        paasFormRichTextEntity.setData(richTextData.toString());
        paasFormRichTextModel.insert(paasFormRichTextEntity);
        //操作日志
        saveLogger(formDataAddDTO, paasFormDataEntity.getDataId());
    }

    @Override
    public Integer updateFormRichText(FormDataUpdateDTO formDataUpdateDTO, Object richTextData) {
        if (Objects.isNull(richTextData)) {
            return 0;
        }
        Long dataId = formDataUpdateDTO.getDataId();
        Integer updateRichTextLine = paasFormRichTextModel.updateFormRichText(formDataUpdateDTO, richTextData);
        //操作日志
        saveLogger(formDataUpdateDTO, dataId);
        return updateRichTextLine;
    }

    @Override
    public PaasFormRichTextEntity getByDataId(Long dataId, String corpid, Long formId, Integer businessType, Integer saasMark, Integer del) {
        PaasFormRichTextEntity entity = new PaasFormRichTextEntity(dataId, corpid, formId, businessType, saasMark, del);
        return paasFormRichTextModel.getByDataId(entity);
    }

    @Override
    public void backupRichText(WorkflowBackupDataEntity workflowBackupDataEntity, Integer businessType, Integer saasMark) {
        PaasFormRichTextEntity entity = this.getByDataId(workflowBackupDataEntity.getDataId(), workflowBackupDataEntity.getCorpid(),
                workflowBackupDataEntity.getFormId(), businessType, saasMark, DelEnum.NORMAL.getDel());
        WorkflowBackupRichTextEntity workflowBackupRichTextEntity = new WorkflowBackupRichTextEntity();
        BeanUtil.copyProperties(workflowBackupDataEntity, workflowBackupRichTextEntity);
        workflowBackupRichTextEntity.setId(null);
        workflowBackupRichTextEntity.setData(Objects.nonNull(entity) ? entity.getData() : "");
        workflowBackupRichTextEntity.setBackupId(workflowBackupDataEntity.getId());
        workflowBackupRichTextModel.insert(workflowBackupRichTextEntity);
    }

    @Override
    public void addRichTextByDataId(Long dataId, String corpid, Long formId, Integer businessType, Integer saasMark, Integer del, JSONObject data) {
        paasFormRichTextModel.addRichTextByDataId(dataId, corpid, formId, businessType, saasMark, del, data);
    }

    @Override
    public void addRichTextByTaskId(Long taskId, String corpid, JSONObject data) {
        PaasProcessRichTextEntity richTextEntity = paasProcessRichTextModel.getByTaskId(taskId, corpid);
        if (Objects.nonNull(richTextEntity)) {
            data.put(RichTextEnum.RICH_TEXT.getAttr(), richTextEntity.getData());
        }
    }

    @Override
    public boolean hasData(String corpid, Long formId) {
        Map<String, Object> params = new HashMap<>(5);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        params.put(StringConstant.START, BasicConstant.ZERO);
        params.put(StringConstant.PAGE_SIZE, BasicConstant.ONE);
        //判断是否有富文本数据
        return paasFormRichTextModel.hasData(params) || paasProcessRichTextModel.hasData(params);
    }

    @Override
    public void operateBatch(FormRichTextBatchDTO batchDTO) {
        paasFormRichTextModel.operateBatch(batchDTO);
    }

    @Override
    public boolean trashDelete(String corpid, Long formId, Integer saasMark, Integer businessType) {
        Map<String, Object> params = new HashMap<>(BasicConstant.FIVE);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        params.put(StringConstant.START, BasicConstant.ZERO);
        params.put(StringConstant.PAGE_SIZE, 501);
        //富文本数据量大于500不允许手动删除
        if (paasFormRichTextModel.countData(params) + paasProcessRichTextModel.countData(params) > 500) {
            return false;
        }
        trashDeleteTask(corpid, formId, saasMark, businessType);
        return true;
    }

    @Override
    public void trashDelete(AttrTrashEntity attrTrashEntity) {
        trashDeleteTask(attrTrashEntity.getCorpid(), attrTrashEntity.getFormId(), attrTrashEntity.getSaasMark(), attrTrashEntity.getBusinessType());
    }

    /**
     * 垃圾回收站删除任务
     *
     * @param corpid
     * @param formId
     */
    private void trashDeleteTask(String corpid, Long formId, Integer saasMark, Integer businessType) {
        Runnable runnable = () -> {
            try {
                //删除字段解释
                removeExplain(corpid, formId, businessType);
                //删除数据
                List<Integer> delList;
                Integer afterDel;
                if (XbbRefTypeEnum.hasRecyleBin(saasMark, businessType)) {
                    delList = Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.DELETE.getDel());
                    afterDel = DelEnum.REMOVE_COMPLETELY.getDel();
                } else {
                    delList = Collections.singletonList(DelEnum.NORMAL.getDel());
                    afterDel = DelEnum.DELETE.getDel();
                }
                paasFormRichTextModel.operateBatch(new FormRichTextBatchDTO(corpid, formId, delList, afterDel));
                if (commonHelp.isOpenWorkFlow(corpid)) {
                    workflowBackupRichTextModel.deleteCompelete(corpid, formId, delList, afterDel);
                } else {
                    paasProcessRichTextModel.deleteCompelete(corpid, formId, delList, afterDel);
                }
            } catch (Exception e) {
                log.error("com.xbongbong.paas.service.impl.RichTextServiceImpl.trashDeleteTask", e);
            }
        };
        threadPoolBeanConfig.attrTrashDelete().execute(runnable);
    }


    /**
     * 移除字段解释
     *
     * @param corpid
     * @param formId
     * @param businessType
     * @throws XbbException
     */
    private void removeExplain(String corpid, Long formId, Integer businessType) throws XbbException {
        PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
        if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderExplainEntity workOrderExplainEntity = workOrderExplainModel.getByFormId(formId, corpid);
            if (Objects.isNull(workOrderExplainEntity)) {
                log.error("com.xbongbong.saas.service.impl.richTextServiceImpl.removeExplain failed,because explain don't exist, corpid=" + corpid + ", formId=" + formId);
            }
            BeanUtil.copyProperties(workOrderExplainEntity, paasFormExplainEntity);
        } else {
            paasFormExplainEntity = paasFormExplainModel.getByFormId(formId, corpid);
            if (Objects.isNull(paasFormExplainEntity)) {
                log.error("com.xbongbong.saas.service.impl.richTextServiceImpl.removeExplain failed,because explain don't exist, corpid=" + corpid + ", formId=" + formId);
            }
        }

        List<FieldAttrEntity> fieldAttrEntities = JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);

        Iterator<FieldAttrEntity> iterator = fieldAttrEntities.iterator();
        while (iterator.hasNext()) {
            FieldAttrEntity fieldAttrEntity = iterator.next();
            String parentAttr = fieldAttrEntity.getAttr();
            if (Objects.equals(parentAttr, RichTextEnum.RICH_TEXT.getAttr()) && Objects.equals(fieldAttrEntity.getIsOpen(), 2)) {
                iterator.remove();
            }
        }

        // 更新解释
        paasFormExplainEntity.setExplains(JSON.toJSONString(fieldAttrEntities, SerializerFeature.DisableCircularReferenceDetect));
        if (Objects.equals(businessType, XbbRefTypeEnum.WORK_ORDER.getCode())) {
            WorkOrderExplainEntity workOrderExplainEntity = new WorkOrderExplainEntity();
            BeanUtil.copyProperties(paasFormExplainEntity, workOrderExplainEntity);
            workOrderExplainModel.update(workOrderExplainEntity);
        } else {
            paasFormExplainModel.update(paasFormExplainEntity);
        }
    }


    /**
     * 保存日志
     *
     * @param objDTO 新增或更新DTO
     * @param dataId 数据Id
     */
    public void saveLogger(Object objDTO, Long dataId) {
        Runnable runnable = () -> {
            try {
                if (objDTO instanceof FormDataAddDTO) {
                    //新增富文本
                    FormDataAddDTO formDataAddDTO = (FormDataAddDTO) objDTO;
                    String corpid = formDataAddDTO.getCorpid();
                    String userName = formDataAddDTO.getLoginUser().getName();
                    String userId = formDataAddDTO.getLoginUser().getUserId();
                    String httpHeader = formDataAddDTO.getHttpHeader();
                    String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_RICH_TEXT), userName);
                    mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_RICH_TEXT, OperateTypeEnum.NEW,
                            dataId.toString(), null, memo, httpHeader);
                } else if (objDTO instanceof FormDataUpdateDTO) {
                    //更新富文本
                    FormDataUpdateDTO formDataUpdateDTO = (FormDataUpdateDTO) objDTO;
                    String corpid = formDataUpdateDTO.getCorpid();
                    String userName = formDataUpdateDTO.getLoginUser().getName();
                    String userId = formDataUpdateDTO.getLoginUser().getUserId();
                    String httpHeader = formDataUpdateDTO.getHttpHeader();
                    String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_RICH_TEXT), userName);
                    mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_RICH_TEXT, OperateTypeEnum.EDIT,
                            dataId.toString(), null, memo, httpHeader);
                }
            } catch (Exception e) {
                log.error("com.xbongbong.paas.service.impl.RichTextServiceImpl.saveLogger fail", e);
            }
        };
        logThreadPoolBeanConfig.sysLogThreadPool().execute(runnable);
    }
}
